package whu.cachhe.makeorder.view;

import android.content.Context;
import android.text.TextUtils;
import android.view.View;

import com.bigkoo.pickerview.OptionsPickerView;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import whu.cachhe.makeorder.domain.TimeInterval;
import whu.cachhe.makeorder.util.DateTimeUtil;
import whu.cachhe.makeorder.util.Logger;

/**
 * 这个类建议重写，直接垒在PickerView上，导致很多实现上的不便。
 * 时间选择组件要实现联动和数据不连续，最好自定义WheelOptions
 * Created by CocoAdapter on 2018/3/21.
 */

public class SimpleDateTimePicker extends OptionsPickerView {
    private ArrayList<String> days;
    private ArrayList<ArrayList<String>> hours;
    private ArrayList<ArrayList<ArrayList<String>>> minutes;

    private OnDateTimeSelectedListener onDateTimeSelectedListener;
    private int year, month, dayOfMonth;

    private Date startTime;
    private TIME_TYPE timeType;
    public enum TIME_TYPE {
        START_TIME, END_TIME;
    }

    private List<TimeInterval> timeIntervals;

    public static final int MIN_INTERVAL = 15;
    public static final int HOUR_INTERVAL = 24;

    public SimpleDateTimePicker(Context context) {
        super(context);
    }

    public void setStartTime(Date startTime){
        this.startTime = DateTimeUtil.parse(startTime);
    }

    public void setTimeType(TIME_TYPE type){
        if (startTime == null && type == TIME_TYPE.END_TIME)
            throw new RuntimeException("请先设置开始时间");

        timeType = type;
    }

    private boolean isDateInHourInterval(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startTime);
        calendar.add(Calendar.HOUR_OF_DAY, HOUR_INTERVAL);
        Date toDate = calendar.getTime();
        return date.after(startTime) && date.before(toDate);
    }

    /**
     *
     * @param excludeTime format yyyy:MM:dd'T'hh:mm:ss
     */
    public void setExcludeTime(JSONArray excludeTime){
        if (timeIntervals == null)
            timeIntervals = new ArrayList<>();

        timeIntervals.clear();
        if (excludeTime == null)
            return;
        for (int i = 0; i < excludeTime.length(); i++){
            try {
                JSONObject object = excludeTime.getJSONObject(i);
                TimeInterval timeInterval = new TimeInterval();
                timeInterval.setStartTime(DateTimeUtil.parse(object.optString("startTime")));
                timeInterval.setEndTime(DateTimeUtil.parse(object.optString("endTime")));

                timeIntervals.add(timeInterval);
            } catch (JSONException e){
                e.printStackTrace();
                timeIntervals.clear();
            }
        }
    }

    /**
     *
     * @param timeFrom 从这个时间开始，之后的时间都不出现, 这个时间是可用的
     */
    public void setExcludeTimeFrom(String timeFrom){
        if (timeIntervals == null)
            timeIntervals = new ArrayList<>();

        timeIntervals.clear();
        TimeInterval timeInterval = new TimeInterval();
        timeInterval.setStartTime(DateTimeUtil.parse(timeFrom));
        timeInterval.setEndTime(new Date(Long.MAX_VALUE));
        timeIntervals.add(timeInterval);
    }

    public void setExcludeTimeFrom(Date timeFrom){
        if (timeIntervals == null)
            timeIntervals = new ArrayList<>();

        timeIntervals.clear();
        if (timeFrom != null){
            TimeInterval timeInterval = new TimeInterval();
            timeInterval.setStartTime(timeFrom);
            timeInterval.setEndTime(new Date(Long.MAX_VALUE));
            timeIntervals.add(timeInterval);
        }
    }

    @Override
    public void show(){
        days = new ArrayList<>();

        days.add("今天");
        days.add("明天");
        days.add("后天");

        Calendar calendar = Calendar.getInstance();
        year = calendar.get(Calendar.YEAR);
        month = calendar.get(Calendar.MONTH);
        dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);

        hours = new ArrayList<>();
        ArrayList<String> hoursOfDay1 = getTodayHourData();
        ArrayList<String> hoursOfDay2 = getNoTodayHourData();
        ArrayList<String> hoursOfDay3 = getNoTodayHourData();

        hours.add(hoursOfDay1);
        hours.add(hoursOfDay2);
        hours.add(hoursOfDay3);


        minutes = new ArrayList<>();
        ArrayList<ArrayList<String>> minutesOfHour1 = getThisHourMinuteData();
        // 有点多余
        String strHour = hoursOfDay1.get(0);
        strHour = strHour.substring(0, strHour.length() - 1);
        int startHour = Integer.parseInt(strHour);
        func(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), startHour,
                minutesOfHour1, timeIntervals);

        ArrayList<ArrayList<String>> minutesOfHour2 = getNoToday();
        strHour = hoursOfDay2.get(0);
        strHour = strHour.substring(0, strHour.length() - 1);
        startHour = Integer.parseInt(strHour);
        calendar.add(Calendar.DATE, 1);
        func(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), startHour,
                minutesOfHour2, timeIntervals);

        ArrayList<ArrayList<String>> minutesOfHour3;
        if (timeType == TIME_TYPE.START_TIME)
            minutesOfHour3 = getAfterTomorrow();
        else
            minutesOfHour3 = getNoToday();

        strHour = hoursOfDay3.get(0);
        strHour = strHour.substring(0, strHour.length() - 1);
        startHour = Integer.parseInt(strHour);
        calendar.add(Calendar.DATE, 1);
        func(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), startHour,
                minutesOfHour3, timeIntervals);

        minutes.add(minutesOfHour1); // 这里为空
        minutes.add(minutesOfHour2);
        minutes.add(minutesOfHour3);

        Iterator<ArrayList<ArrayList<String>>> minIt = minutes.iterator();
        Iterator<ArrayList<String>> hourIt = hours.iterator();
        Iterator<String> dayIt = days.iterator();
        while (minIt.hasNext()){
            dayIt.next();
            ArrayList<ArrayList<String>> big = minIt.next(); // 第N天的时分信息 [[], [], [], [0分]]
            ArrayList<String> hour = hourIt.next(); // 第N天的时信息 [20点, 21点, 22点, 23点]

            Iterator<ArrayList<String>> medIt = big.iterator(); // 第M时的分信息
            Iterator<String> hourMedIt = hour.iterator(); // 第M时
            while (medIt.hasNext()){
                ArrayList<String> med = medIt.next();
                hourMedIt.next();
                if (med.isEmpty()){
                    medIt.remove();
                    hourMedIt.remove();
                }
            }
            if(hourMedIt.hasNext()){
                while (hourMedIt.hasNext()){
                    hourMedIt.next();
                    hourMedIt.remove();
                }
            }

            // 清空第N天的时分信息 和 时信息
            if (big.isEmpty()){
                hour.clear(); // 清空第N天的时信息
            }

            if (hour.isEmpty()){
                dayIt.remove();
                hourIt.remove();
                minIt.remove();
            }
        }


        Logger.e(days.toString());
        Logger.e(hours.toString());
        Logger.e(minutes.toString());

        //三级联动效果
        setPicker(days, hours, minutes, true);

        //设置选择的三级单位
        setCyclic(false, false, false);
        //设置默认选中的三级项目
        //监听确定选择按钮
        setSelectOptions(0, 0, 0);

        super.show();
    }
    /*
        一个非常不优雅的删除方式
         */
    private void func(int year, int month, int dayOfMonth, int startHour,
                      ArrayList<ArrayList<String>> minutesOfHour, List<TimeInterval> timeIntervals){
        if(timeIntervals != null){
            Collections.sort(timeIntervals, new Comparator<TimeInterval>() {
                @Override
                public int compare(TimeInterval o1, TimeInterval o2) {
                    Date startO1 = o1.getStartTime();
                    Date startO2 = o2.getStartTime();
                    if (startO1 != null && startO2 != null)
                        return startO1.compareTo(startO2);
                    else
                        return 1; // 往后排
                }
            });
        }

        for (int i = 0; i < minutesOfHour.size(); i++){
            boolean flag = false;

            int hour = startHour + i;

            Calendar calendar = Calendar.getInstance();
            calendar.set(year, month, dayOfMonth);
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 0);

            calendar.set(Calendar.HOUR_OF_DAY, hour);

            ArrayList<String> minutes = minutesOfHour.get(i);
//            Logger.e(minutes.toString());
            Iterator<String> it = minutes.iterator();
            while (it.hasNext()){
                String strMin = it.next();

                if (strMin != null){
                    strMin = strMin.substring(0, strMin.length() - 1);
                    int min = Integer.parseInt(strMin);

                    calendar.set(Calendar.MINUTE, min);
                    Date targetTime = calendar.getTime();

                    if (timeIntervals == null || timeIntervals.isEmpty()){
                        // 只比较 startTime 和 endTime
                        if (timeType == TIME_TYPE.END_TIME && !isDateInHourInterval(targetTime)){
                            it.remove();
                        }
                    } else {
                        for (TimeInterval ti : timeIntervals){
                            Date sTime = ti.getStartTime();
                            Date eTime = ti.getEndTime();
                            if (sTime == null || eTime == null)
                                continue;

                            if (timeType == TIME_TYPE.START_TIME){
                                if (targetTime.before(sTime) || targetTime.compareTo(eTime) >= 0)
                                    continue;
                                else{
                                    it.remove();
                                    break;
                                }
                            } else if (timeType == TIME_TYPE.END_TIME){
                                if (!isDateInHourInterval(targetTime)){
                                    it.remove();
                                    break;
                                } else if (sTime.after(startTime) && targetTime.compareTo(sTime) > 0){
                                    flag = true;
                                    break; // 只比第一个时间
                                }
                            }
                        }

                        if (flag){
                            it.remove();
                            while (it.hasNext()){
                                it.next();
                                it.remove();
                            }
                            break;
                        }
                    }
                }
            }

            if (flag){
                //
                int j = i + 1;
                while (j < minutesOfHour.size()){
                    minutesOfHour.remove(j);
                }
                return;
            }
        }
    }

    /**
     * 今天 剩余 小时
     *
     */
    private ArrayList<String> getTodayHourData() {
        int currentHour = currentHour();
        if (currentHour < 23 && currentMinute() > (60 - MIN_INTERVAL)) {
            currentHour = currentHour + 1;
        }
        ArrayList<String> lists = new ArrayList<>();
        for (int i = currentHour; i < 24; i++) {
            lists.add(i + "点");
        }
        return lists;
    }

    /**
     * 当前小时下 的可用分钟, 去除掉不可选的时间
     */
    private ArrayList<ArrayList<String>> getThisHourMinuteData(){ // TODO 去除掉不可选的时间
        ArrayList<ArrayList<String>> data = new ArrayList<>();
        int currentHour = currentHour();
        boolean isNextHour = false; // 从下一个小时开始
        if (currentMinute() >= (60 - MIN_INTERVAL)) {
            currentHour = currentHour + 1;
            isNextHour = true;
        }

        int value = 24 - currentHour;
        for (int i = 0; i < value; i++) { // 今天还有几个小时
            if (i == 0) {
                ArrayList<String> minData = new ArrayList<>(); // 这个小时的可选分钟
                if (isNextHour){
                    for (int j = 0; j < 60 / MIN_INTERVAL; j++){
                        // 比较一下时间 hour拿不到，日期拿不到

                        minData.add((j * MIN_INTERVAL) + "分");
                    }
                } else {
                    int start = (int) (Math.floor(currentMinute() / (double) MIN_INTERVAL)) + 1;
                    if (start >= (60 / MIN_INTERVAL))
                        minData.add(null);
                    else {
                        for (int j = start; j < 60 / MIN_INTERVAL; j++){
                            minData.add((j * MIN_INTERVAL) + "分");
                        }
                    }
                }
                data.add(minData);
            } else { // 非当前小时 可选分钟
                data.add(getNoThisHourMinuteData());
            }

        }
        return data;
    }

    /**
     * 非今天 的可用分钟
     */
    private ArrayList<String> getNoTodayHourData() {
        ArrayList<String> lists = new ArrayList<>();
        for (int i = 0; i < 24; i++) {
            lists.add(i + "点");
        }
        return lists;
    }

    private ArrayList<String> getNoThisHourMinuteData(){
        ArrayList<String> minData = new ArrayList<>();
        int tem = 60 / MIN_INTERVAL;
        for (int j = 0; j < tem; j++){
            minData.add((j * MIN_INTERVAL) + "分");
        }
        return minData;
    }

    /**
     * 非今天 关联
     * 24个小时 和 每个小时的分钟数, 去除掉不可选的时间
     */
    private ArrayList<ArrayList<String>> getNoToday(){
        ArrayList<ArrayList<String>> data = new ArrayList<>();
        for (int i = 0; i < 24; i++){
            data.add(getNoThisHourMinuteData());
        }
        return data;
    }

    private ArrayList<ArrayList<String>> getAfterTomorrow(){
        ArrayList<ArrayList<String>> data = new ArrayList<>();
        for (int i = 0; i < 24; i++){
            data.add(getNoThisHourMinuteData());
        }

        ArrayList<String> theLastHour = data.get(data.size() - 1);
        theLastHour.remove(theLastHour.size() - 1);
        return data;
    }

    private int currentMinute() {
        Calendar cal = Calendar.getInstance();
        return cal.get(Calendar.MINUTE);
    }

    private int currentHour() {
        Calendar cal = Calendar.getInstance();
        return cal.get(Calendar.HOUR_OF_DAY);
    }

    public interface OnDateTimeSelectedListener {
        void onDateTimeSelected(int year, int month, int dayOfMonth, int hourOfDay, int minute);
    }

    public void setOnDateTimeSelectedListener(OnDateTimeSelectedListener onDateTimeSelectedListener){
        this.onDateTimeSelectedListener = onDateTimeSelectedListener;
    }

    @Override
    public void onClick(View v){
        String tag=(String) v.getTag();
        if(tag.equals(TAG_CANCEL)) {
            dismiss();
        } else {
            if(onDateTimeSelectedListener!=null) {
                int[] optionsCurrentItems = wheelOptions.getCurrentItems();

                Calendar calendar = Calendar.getInstance();
                calendar.set(year, month, dayOfMonth);
                if (days.get(optionsCurrentItems[0]).equals("今天"))
                    calendar.add(Calendar.DAY_OF_MONTH, 0);
                else if (days.get(optionsCurrentItems[0]).equals("明天"))
                    calendar.add(Calendar.DAY_OF_MONTH, 1);
                else if (days.get(optionsCurrentItems[0]).equals("后天"))
                    calendar.add(Calendar.DAY_OF_MONTH, 2);

                String strHour = hours.get(optionsCurrentItems[0]).get(optionsCurrentItems[1]);
                strHour = strHour.substring(0, strHour.length() - 1);
                String strMinute = minutes.get(optionsCurrentItems[0]).get(optionsCurrentItems[1]).get(optionsCurrentItems[2]);
                if (TextUtils.isEmpty(strMinute)){
                    return; // 不能选择, 直接返回
                } else
                    strMinute = strMinute.substring(0, strMinute.length() - 1);

                calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(strHour));
                calendar.set(Calendar.MINUTE, Integer.parseInt(strMinute));
                onDateTimeSelectedListener.onDateTimeSelected(
                        calendar.get(Calendar.YEAR),
                        calendar.get(Calendar.MONTH),
                        calendar.get(Calendar.DAY_OF_MONTH),
                        calendar.get(Calendar.HOUR_OF_DAY),
                        calendar.get(Calendar.MINUTE)
                );
            }
            dismiss();
        }
    }
}
